package com.os;

import com.graphics.ImageIdentity;
import com.ip.TilePattern;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import mapgenerator.Main;

/**
 *
 * @author Sajarwo Anggai
 */
public class ObjectSpriteControlPanel implements TreeSelectionListener, ActionListener, ChangeListener {

    private Main comp;
    private String currentPosition = "";
    public ObjectSprite currentSprite;
    private ArrayList currentBound = null;
    private SpriteAnimator spriteAnimator;
    public static int edgeX = 50, edgeY = 50;

    public ObjectSpriteControlPanel(Main comp) {
        this.comp = comp;
        comp.ButtonAddObjectSpriteLeftPanel.addActionListener(this);
        comp.ObjectSpriteButtonAddToPattern.addActionListener(this);
        comp.ObjectSpriteButtonSetOnWorkspace.addActionListener(this);
        comp.ObjectSpriteButtonRename.addActionListener(this);
        comp.ObjectSpriteButtonRemove.addActionListener(this);
        comp.ObjectSpriteButtonPlay.addActionListener(this);
        comp.ObjectSpriteButtonPause.addActionListener(this);
        comp.ObjectSpriteButtonStop.addActionListener(this);
        comp.ObjectSpriteDelayAnimationTime.addChangeListener(this);
        comp.AddNew.addActionListener(this);
        comp.Remove.addActionListener(this);
        comp.Edit.addActionListener(this);
        comp.MoveUp.addActionListener(this);
        comp.MoveDown.addActionListener(this);
        comp.DrawOnLayer.addActionListener(this);
        comp.UpdatePositionSprite.addActionListener(this);
        comp.SetNullPositionSprite.addActionListener(this);
        spriteAnimator = new SpriteAnimator(comp);
    }

    public void showImgeManagerInfo(boolean activate) {
        comp.ObjectSpriteButtonAddToPattern.setVisible(activate);
        comp.ObjectSpriteButtonRename.setVisible(activate);
        comp.ObjectSpriteButtonRemove.setVisible(activate);
        comp.ObjectSpriteButtonSetOnWorkspace.setVisible(activate);
        comp.ObjectSpriteButtonPlay.setVisible(activate);
        comp.ObjectSpriteButtonPause.setVisible(activate);
        comp.ObjectSpriteButtonStop.setVisible(activate);
        comp.OSLabelOperation.setVisible(activate);
    }

    @Override
    public void valueChanged(TreeSelectionEvent e) {
        if (!comp.project.isCreated()) {
            return;
        }
        try {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) comp.osPanelWidget.getTree().getLastSelectedPathComponent();
            comp.ObjectSpriteRightPanelRender.setVisible(false);
            if (node == null) {
                return;
            } else if (node.isLeaf()) {
                currentSprite = (ObjectSprite) ((DefaultMutableTreeNode) node.getParent()).getUserObject();
                currentPosition = node.toString();
                setPositionBoundingBox();
                if (currentPosition.equals(currentSprite.getDrawOnLayer())) {
                    comp.DrawOnLayer.setSelected(true);
                } else {
                    comp.DrawOnLayer.setSelected(false);
                }
                show();
            } else if (!node.isRoot()) {
                currentSprite = (ObjectSprite) node.getUserObject();
                currentPosition = "";
                currentBound = null;
                showImgeManagerInfo(true);
                comp.ObjectSpriteButtonAddToPattern.setVisible(false);
                comp.ObjectSpriteButtonPlay.setVisible(false);
                comp.ObjectSpriteButtonPause.setVisible(false);
                comp.ObjectSpriteButtonStop.setVisible(false);
                comp.OSLabelOperation.setVisible(false);
            } else {
                currentPosition = "";
                currentSprite = null;
                currentBound = null;
                showImgeManagerInfo(false);
            }
        } catch (Exception err) {
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (!comp.project.isCreated()) {
            return;
        }
        Object ob = e.getSource();
        if (ob == comp.ButtonAddObjectSpriteLeftPanel) {
            OSDialogCreateSprite dcs = new OSDialogCreateSprite(comp);
            dcs.setModal(true);
            dcs.setVisible(true);
        } else if (ob == comp.ObjectSpriteButtonAddToPattern) {
            OSDialogAddFrame daf = new OSDialogAddFrame(comp);
            spriteAnimator.setVisible(true);
            daf.setModal(true);
            daf.setVisible(true);
        } else if (ob == comp.ObjectSpriteButtonPlay) {
            spriteAnimator.setVisible(true);
            spriteAnimator.playAnim();
            comp.ObjectSpriteButtonPlay.setEnabled(false);
            comp.ObjectSpriteButtonPause.setEnabled(true);
            comp.ObjectSpriteButtonStop.setEnabled(true);
        } else if (ob == comp.ObjectSpriteButtonPause) {
            spriteAnimator.pauseAnim();
            comp.ObjectSpriteButtonPlay.setEnabled(true);
            comp.ObjectSpriteButtonPause.setEnabled(false);
            comp.ObjectSpriteButtonStop.setEnabled(true);
        } else if (ob == comp.ObjectSpriteButtonStop) {
            spriteAnimator.stopAnim();
            comp.ObjectSpriteButtonPlay.setEnabled(true);
            comp.ObjectSpriteButtonPause.setEnabled(false);
            comp.ObjectSpriteButtonStop.setEnabled(false);
        } else if (ob == comp.ObjectSpriteButtonRename) {
            while (true) {
                String message = (String) JOptionPane.showInputDialog(comp, "Please rename object sprite.", "Rename File", JOptionPane.OK_CANCEL_OPTION);
                try {
                    if (message.trim().equals("")) {
                        return;
                    }
                } catch (NullPointerException ev) {
                    return;
                }
                if (comp.osContainer.renameSprites(currentSprite, message)) {
                    break;
                }
            }
            comp.osPanelWidget.reloadAll();
        } else if (ob == comp.ObjectSpriteButtonRemove) {
            spriteAnimator.setVisible(false);
            if (currentSprite == currenObjectSpriteOnWorkspace) {
                comp.WorkspaceBottomSprite.removeAll();
                comp.WorkspaceBottomSprite.repaint();
                comp.WorkspaceBottomSprite.revalidate();
                currenObjectSpriteOnWorkspace = null;
                comp.PositionXSprite.setText("");
                comp.PositionYSprite.setText("");
            }
            comp.osContainer.removeSprites(currentSprite);
            comp.osPanelWidget.reloadAll();
        } else if (ob == comp.AddNew) {
            OSDialogBoundingBox bounding = new OSDialogBoundingBox(comp);
            bounding.setModal(true);
            bounding.setVisible(true);
        } else if (ob == comp.Edit) {
            try {
                OSBoundingBox osb = (OSBoundingBox) currentBound.get(comp.ObjectSpriteListOfBound.getSelectedIndex());
                OSDialogBoundingBox bounding = new OSDialogBoundingBox(comp);
                bounding.setBound(osb);
                bounding.setModal(true);
                bounding.setVisible(true);
            } catch (Exception err) {
            }
        } else if (ob == comp.Remove) {
            int list[] = comp.ObjectSpriteListOfBound.getSelectedIndices();
            Arrays.sort(list);
            for (int i = list.length - 1; i >= 0; i--) {
                removeBoundingBox(list[i]);
            }
        } else if (ob == comp.MoveUp) {
            int indexRow = comp.ObjectSpriteListOfBound.getSelectedIndex();
            if (indexRow != -1 && indexRow != 0) {
                Object tmp = currentBound.get(indexRow);
                currentBound.set(indexRow, currentBound.get(indexRow - 1));
                currentBound.set(indexRow - 1, tmp);
                showBoundingBox();
            }
        } else if (ob == comp.MoveDown) {
            int indexRow = comp.ObjectSpriteListOfBound.getSelectedIndex();
            if (indexRow != -1 && indexRow != currentBound.size() - 1) {
                Object tmp = currentBound.get(indexRow);
                currentBound.set(indexRow, currentBound.get(indexRow + 1));
                currentBound.set(indexRow + 1, tmp);
                showBoundingBox();
            }
        } else if (ob == comp.ObjectSpriteButtonSetOnWorkspace) {
            showOnWorkspace(comp.WorkspaceBottomSprite, currentSprite);
            if (currentSprite.getPosition() != null) {
                comp.PositionXSprite.setText("" + currentSprite.getPosition().x);
                comp.PositionYSprite.setText("" + currentSprite.getPosition().y);
            } else {
                comp.PositionXSprite.setText("");
                comp.PositionYSprite.setText("");
            }
            currenObjectSpriteOnWorkspace = currentSprite;
        } else if (ob == comp.DrawOnLayer) {
            if (comp.DrawOnLayer.isSelected()) {
                currentSprite.setDrawOnLayer(currentPosition);
            } else {
                currentSprite.setDrawOnLayer("");
            }
        } else if (ob == comp.UpdatePositionSprite) {
            try {
                int x = Integer.parseInt(comp.PositionXSprite.getText());
                int y = Integer.parseInt(comp.PositionYSprite.getText());
                setSpritePosition(x, y, true);
            } catch (Exception eee) {
            }
        } else if (ob == comp.SetNullPositionSprite) {
            setSpritePosition(0, 0, false);
        }        
    }

    /**
     * Sep posisi sprite yang diset active pada workspace
     * @param x koordinat x
     * @param y koordinat t
     * @param op true untuk set posisi dan false untuk menghapus
     */
    public void setSpritePosition(int x, int y, boolean op) {
        if (op) {
            if (currenObjectSpriteOnWorkspace.getPosition() == null) {
                currenObjectSpriteOnWorkspace.setPosition(new Point(x, y));
            } else {
                currenObjectSpriteOnWorkspace.getPosition().setLocation(x, y);
            }
            comp.PositionXSprite.setText("" + x);
            comp.PositionYSprite.setText("" + y);
        } else {
            currenObjectSpriteOnWorkspace.setPosition(null);
            comp.PositionXSprite.setText("");
            comp.PositionYSprite.setText("");
        }
        comp.lmControlPanel.gridWorkspace.drawSprite();
        this.comp.ScrollPaneWorkspaceRender.repaint();
    }

    public void setPositionBoundingBox() {
        if (currentSprite.getAttribute(currentPosition) == null) {
            return;
        }
        currentBound = currentSprite.getAttribute(currentPosition).getBound();
    }

    public void addBoundingBox(OSBoundingBox bound) {
        currentBound.add(bound);
        showBoundingBox();
    }

    public void editBoundingBox(OSBoundingBox src, OSBoundingBox dst) {
        currentBound.set(currentBound.indexOf(src), dst);
        showBoundingBox();
    }

    public void removeBoundingBox(int index) {
        currentBound.remove(index);
        showBoundingBox();
    }

    public void showBoundingBox() {
        comp.ObjectSpriteListOfBound.setListData(currentBound.toArray());
    }

    public void setFrame(ImageIdentity ident) {
        if (currentSprite.getAttribute(currentPosition) == null) {
            currentSprite.getAllAttribute().put(currentPosition, new OSAttribute());
            currentSprite.getAttribute(currentPosition).setName(ident.getName());
            currentSprite.getAttribute(currentPosition).setAttributeName(currentPosition);
        }
        currentSprite.getAttribute(currentPosition).setAttrib(ident);
        currentSprite.getAttribute(currentPosition).setTime(10);
        if (currentSprite == currenObjectSpriteOnWorkspace) {
            showOnWorkspace(comp.WorkspaceBottomSprite, currenObjectSpriteOnWorkspace);
        }
    }
    private ObjectSprite currenObjectSpriteOnWorkspace;

    public void showOnWorkspace(JPanel render, ObjectSprite obSprite) {
        render.removeAll();
        try {
            if (obSprite.getAllAttribute().size() != 0) {
                int tmpWidth = 0, tmpHeight = 0;
                int width = 0, height = 0, time = 0;
                int x = 10, y = 10;

                Iterator itr = obSprite.getAllAttribute().keySet().iterator();
                while (itr.hasNext()) {
                    String key = (String) itr.next();
                    OSAttribute oa = obSprite.getAttribute(key);
                    ImageIdentity ident = oa.getAttrib();
                    for (int i = 0; i < ident.getImages().size(); i++) {
                        TilePattern tp = new TilePattern(ident, i);
                        tp.setToolTipText(obSprite.getName() + " Position = " + key);
                        width = tp.getImage().getWidth();
                        height = tp.getImage().getHeight();
                        render.add(tp).setBounds(x, y, width, height);
                        if ((i + 1) % ident.getCols() == 0) {
                            x = 10;
                            y += height + comp.ipControlPanel.getVGap();
                        } else {
                            x += width + comp.ipControlPanel.getHGap();
                        }
                    }
                    tmpWidth = Math.max(tmpWidth, ident.getCols() * width);
                    tmpHeight = Math.max(tmpHeight, ident.getRows() * height);
                }
                render.setPreferredSize(new Dimension(tmpWidth + 20, y + 20));
                currenObjectSpriteOnWorkspace = currentSprite;
            } else {
                currenObjectSpriteOnWorkspace = null;
            }
        } catch (Exception e) {
            currenObjectSpriteOnWorkspace = null;
        }
        render.repaint();
        render.revalidate();
    }

    public void setSpriteAnimation(boolean started) {
        if (currentSprite != null) {
            if (spriteAnimator.isRunning()) {
                spriteAnimator.stop();
            }
            try {
                BufferedImage bi = null;
                int width, height, time = 0;
                ArrayList tmp = null;

                tmp = currentSprite.getAttribute(currentPosition).getAttrib().getImages();
                time = currentSprite.getAttribute(currentPosition).getTime();
                bi = (BufferedImage) tmp.get(0);
                spriteAnimator.setSprite(tmp, time, started);
                width = bi.getWidth() + (ObjectSpriteControlPanel.edgeX * 2);
                height = bi.getHeight() + (ObjectSpriteControlPanel.edgeY * 2);
                spriteAnimator.setSize(width, height);
                spriteAnimator.setBound(currentBound);
                comp.ObjectSpriteRightPanelRender.add(spriteAnimator).setBounds(200, 10, width, height);
                comp.ObjectSpriteRightPanelRender.setPreferredSize(new Dimension(width + 200, height + 200));
                spriteAnimator.start();
                comp.ObjectSpriteRightPanelRender.setVisible(true);
            } catch (Exception e) {
                comp.ObjectSpriteRightPanelRender.setVisible(false);
                comp.ObjectSpriteButtonPlay.setVisible(false);
                comp.ObjectSpriteButtonPause.setVisible(false);
                comp.ObjectSpriteButtonStop.setVisible(false);
            }
            comp.ObjectSpriteRightPanelRender.repaint();
            comp.ObjectSpriteRightPanelRender.revalidate();
        }

    }

    @Override
    public void stateChanged(ChangeEvent e) {
        try {
            int time = Integer.parseInt("" + comp.ObjectSpriteDelayAnimationTime.getValue());
            if (time < 1) {
                time = 1;
                comp.ObjectSpriteDelayAnimationTime.setValue(time);
            }
            currentSprite.getAttribute(currentPosition).setTime(time);
            show();
        } catch (Exception err) {
        }
    }

    public void show() {
        showImgeManagerInfo(true);
        setSpriteAnimation(true);
        spriteAnimator.setVisible(true);
        spriteAnimator.stopAnim();
        showBoundingBox();
        comp.ObjectSpriteButtonPlay.setEnabled(true);
        comp.ObjectSpriteButtonPause.setEnabled(false);
        comp.ObjectSpriteButtonStop.setEnabled(false);
        comp.ObjectSpriteDelayAnimationTime.setValue(currentSprite.getAttribute(currentPosition).getTime());
    }

    public ObjectSprite getCurrenObjectSpriteOnWorkspace() {
        return currenObjectSpriteOnWorkspace;
    }
}

        